package com.topsec.erp.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.lang.reflect.Method;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * author: zsl
 * date: 2019/11/25 15:29
 * Description: 线程池配置
 */
@Configuration
@EnableAsync
public class TaskExecutorConfig  implements AsyncConfigurer {

    // 日志
    private static final Logger log = LoggerFactory.getLogger(TaskExecutorConfig.class);

    // ThredPoolTaskExcutor的处理流程
    // 当池子大小小于corePoolSize，就新建线程，并处理请求
    // 当池子大小等于corePoolSize，把请求放入workQueue中，池子里的空闲线程就去workQueue中取任务并处理
    // 当workQueue放不下任务时，就新建线程入池，并处理请求，如果池子大小撑到了maximumPoolSize，就用RejectedExecutionHandler来做拒绝处理
    // 当池子的线程数大于corePoolSize时，多余的线程会等待keepAliveTime长时间，如果无请求可处理就自行销毁
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(100);             // 当前线程数
        taskExecutor.setMaxPoolSize(500);              // 最大线程数
        taskExecutor.setQueueCapacity(300);             // 线程池所使用的缓冲队列
        taskExecutor.setKeepAliveSeconds(200);    // 线程池维护线程所允许的空闲时间
        taskExecutor.setWaitForTasksToCompleteOnShutdown(true);     // 等待任务在关机时完成--表明等待所有线程执行完
        taskExecutor.setAwaitTerminationSeconds(60 * 15);           // 等待时间 （默认为0，此时立即停止），并没等待xx秒后强制停止
        taskExecutor.setThreadNamePrefix("appWeb-Executor-");       // 线程名称前缀
        // rejection-polocy：当pool已经达到max size的时候，如何处理新任务
        // CALLER_RUN：不在新线程中执行任务，而是由调用者所在的线程来执行
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

        taskExecutor.initialize();                     // 初始化
        System.out.println(" =====================>>>> 开启线程池");

        return taskExecutor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new MyAsyncExceptionHandler();
    }

    /**
     * 自定义异常处理类
     *
     * @author hry
     */
    class MyAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {

        //手动处理捕获的异常
        @Override
        public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
            System.out.println(" ===>>> 捕获线程池中线程异常信息");
            log.info("Exception message - " + throwable.getMessage());
            log.info("Method name - " + method.getName());
            for (Object param : obj) {
                log.info("Parameter value - " + param);
            }
        }
    }
}